package com.xcyy.zjdxmjk.zjdxmjk.common;

import com.xcyy.zjdxmjk.zjdxmjk.entity.TokenInfo;
import com.xcyy.zjdxmjk.zjdxmjk.repository.TokenRepository;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * 描述:
 *
 * @author Alec
 * @create 2019-12-25 10:01
 */
public class JwtTokenInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        //自动排除生成token的路径,并且如果是options请求是cors跨域预请求，设置allow对应头信息
        if(request.getRequestURI().equals("/token") || RequestMethod.OPTIONS.toString().equals(request.getMethod()))
        {
            return true;
        }

        //其他请求获取头信息
        final String authHeader = request.getHeader("ZJD-Token");
        try {
            //如果没有header信息
            if (authHeader == null || authHeader.trim() == "") {
                throw new SignatureException("not found ZJD-Token.");
            }

            //获取jwt实体对象接口实例
            final Claims claims = Jwts.parser().setSigningKey("Alec")
                    .parseClaimsJws(authHeader).getBody();
            //从数据库中获取token
            TokenRepository tokenRepository=getDAO(TokenRepository.class,request);
            TokenInfo token = tokenRepository.findByUserId(claims.getSubject());
            //数据库中的token值
            String tokenval = new String(token.getToken());
            //如果内存中不存在,提示客户端获取token
            if(tokenval == null || tokenval.trim() == "") {
                throw new SignatureException("not found token info, please get token agin.");
            }
            //判断内存中的token是否与客户端传来的一致
            if(!tokenval.equals(authHeader))
            {
                throw new SignatureException("not found token info, please get token agin.");
            }else {
                long dbBuildTime= Long.valueOf(token.getBuildTime());
                long currentTime= System.currentTimeMillis();
                long second= TimeUnit.MICROSECONDS.toSeconds(currentTime-dbBuildTime);
                if (second>7200){
                    throw new SignatureException("token expired!");
                }
            }
        }
        //验证异常处理
        catch (SignatureException  e)
        {
            //输出对象
            PrintWriter writer = response.getWriter();

            //输出error消息
            writer.write(e.getMessage());
            writer.close();
           // response.sendRedirect("/login.html");
            return false;
        }
        //出现异常时
        catch (final Exception e)
        {
            //输出对象
            PrintWriter writer = response.getWriter();
            //输出error消息
            writer.write(e.getMessage());
            writer.close();
            return false;
        }
        return true;
    }
    /**
     * 根据传入的类型获取spring管理的对应dao
     * @param clazz 类型
     * @param request 请求对象
     * @param <T>
     * @return
     */
    private <T> T getDAO(Class<T> clazz, HttpServletRequest request)
    {
        BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return factory.getBean(clazz);
    }
}